package laba7.taskB;

import interfaces.task7.executor.Executor;
import interfaces.task7.executor.Task;
import interfaces.task7.executor.TasksStorage;

/**
 * Implementation of the Executor
 *
 * @author yakimovich
 */
public class ExecutorImpl implements Executor {

    private TasksStorage storage;
    private boolean isStart;
    public static final int MAX_TRY_COUNT = 5;
    public static final int TIME_SLEEP = 100;

    /**
     * The method sets storage for this task.
     *
     * @param ts the storage in which the task
     */
    @Override
    public void setStorage(TasksStorage ts) {
        if (ts == null) {
            throw new NullPointerException();
        }
        this.storage = ts;
    }

    /**
     * The method sets the storage for this task.
     *
     * @return TaskStorage for this Executor
     */
    @Override
    public TasksStorage getStorage() {
        return storage;
    }

    /**
     * The method sets start mode.
     */
    @Override
    public void start() {
        if (isStart == true) {
            throw new IllegalStateException();
        }
        isStart = true;
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                while (isStart) {
                    System.out
                            .println(Thread.currentThread()
                            + " The number of tasks in the storage: "
                            + storage.count());
                    tryExecute();
                    try {
                        Thread.sleep(TIME_SLEEP);
                    } catch (InterruptedException e) {
                        System.out.println(e);
                    }
                }
            }
        });
        thread.start();
    }

    /**
     * The method try execute the task.
     */
    private void tryExecute() {
        Task task = storage.get();
        if (task != null) {
            task.incTryCount();
            try {
                if (!task.execute()) {
                    putBackTask(task);
                }
            } catch (Exception e) {
                putBackTask(task);
            }
        }
    }

    /**
     * The method put the task in a storage.
     */
    private void putBackTask(Task task) {
        int count = task.getTryCount();
        if (count <= MAX_TRY_COUNT) {
            storage.add(task);
            System.out.println("The task put back "
                    + Thread.currentThread().getName());
        }
    }

    /**
     * The method sets start mode.
     */
    @Override
    public void stop() {
        if (isStart == false) {
            throw new IllegalStateException();
        }
        isStart = false;
    }
}
